diff options
Diffstat (limited to 'src/core/hle/service/am/service/library_applet_self_accessor.cpp')
-rw-r--r-- | src/core/hle/service/am/service/library_applet_self_accessor.cpp | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.cpp b/src/core/hle/service/am/service/library_applet_self_accessor.cpp new file mode 100644 index 000000000..a432a79ba --- /dev/null +++ b/src/core/hle/service/am/service/library_applet_self_accessor.cpp @@ -0,0 +1,322 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core_timing.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h" +#include "core/file_sys/registered_cache.h" +#include "core/hle/service/acc/profile_manager.h" +#include "core/hle/service/am/applet_data_broker.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/frontend/applets.h" +#include "core/hle/service/am/service/library_applet_self_accessor.h" +#include "core/hle/service/am/storage.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/glue/glue_manager.h" +#include "core/hle/service/ns/ns.h" +#include "core/hle/service/sm/sm.h" + +namespace Service::AM { + +namespace { + +AppletIdentityInfo GetCallerIdentity(Applet& applet) { + if (const auto caller_applet = applet.caller_applet.lock(); caller_applet) { + // TODO: is this actually the application ID? + return { + .applet_id = caller_applet->applet_id, + .application_id = caller_applet->program_id, + }; + } else { + return { + .applet_id = AppletId::QLaunch, + .application_id = 0x0100000000001000ull, + }; + } +} + +} // namespace + +ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_, + std::shared_ptr<Applet> applet) + : ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, m_applet{std::move(applet)}, + m_broker{m_applet->caller_applet_broker} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&ILibraryAppletSelfAccessor::PopInData>, "PopInData"}, + {1, D<&ILibraryAppletSelfAccessor::PushOutData>, "PushOutData"}, + {2, D<&ILibraryAppletSelfAccessor::PopInteractiveInData>, "PopInteractiveInData"}, + {3, D<&ILibraryAppletSelfAccessor::PushInteractiveOutData>, "PushInteractiveOutData"}, + {5, D<&ILibraryAppletSelfAccessor::GetPopInDataEvent>, "GetPopInDataEvent"}, + {6, D<&ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent>, "GetPopInteractiveInDataEvent"}, + {10, D<&ILibraryAppletSelfAccessor::ExitProcessAndReturn>, "ExitProcessAndReturn"}, + {11, D<&ILibraryAppletSelfAccessor::GetLibraryAppletInfo>, "GetLibraryAppletInfo"}, + {12, D<&ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo>, "GetMainAppletIdentityInfo"}, + {13, D<&ILibraryAppletSelfAccessor::CanUseApplicationCore>, "CanUseApplicationCore"}, + {14, D<&ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo>, "GetCallerAppletIdentityInfo"}, + {15, D<&ILibraryAppletSelfAccessor::GetMainAppletApplicationControlProperty>, "GetMainAppletApplicationControlProperty"}, + {16, D<&ILibraryAppletSelfAccessor::GetMainAppletStorageId>, "GetMainAppletStorageId"}, + {17, D<&ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfoStack>, "GetCallerAppletIdentityInfoStack"}, + {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"}, + {19, D<&ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout>, "GetDesirableKeyboardLayout"}, + {20, nullptr, "PopExtraStorage"}, + {25, nullptr, "GetPopExtraStorageEvent"}, + {30, nullptr, "UnpopInData"}, + {31, nullptr, "UnpopExtraStorage"}, + {40, nullptr, "GetIndirectLayerProducerHandle"}, + {50, D<&ILibraryAppletSelfAccessor::ReportVisibleError>, "ReportVisibleError"}, + {51, D<&ILibraryAppletSelfAccessor::ReportVisibleErrorWithErrorContext>, "ReportVisibleErrorWithErrorContext"}, + {60, D<&ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage>, "GetMainAppletApplicationDesiredLanguage"}, + {70, D<&ILibraryAppletSelfAccessor::GetCurrentApplicationId>, "GetCurrentApplicationId"}, + {80, nullptr, "RequestExitToSelf"}, + {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"}, + {100, nullptr, "CreateGameMovieTrimmer"}, + {101, nullptr, "ReserveResourceForMovieOperation"}, + {102, nullptr, "UnreserveResourceForMovieOperation"}, + {110, D<&ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers>, "GetMainAppletAvailableUsers"}, + {120, nullptr, "GetLaunchStorageInfoForDebug"}, + {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, + {140, nullptr, "SetApplicationMemoryReservation"}, + {150, D<&ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually>, "ShouldSetGpuTimeSliceManually"}, + {160, D<&ILibraryAppletSelfAccessor::Cmd160>, "Cmd160"}, + }; + // clang-format on + RegisterHandlers(functions); +} + +ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; + +Result ILibraryAppletSelfAccessor::PopInData(Out<SharedPointer<IStorage>> out_storage) { + LOG_INFO(Service_AM, "called"); + R_RETURN(m_broker->GetInData().Pop(out_storage)); +} + +Result ILibraryAppletSelfAccessor::PushOutData(SharedPointer<IStorage> storage) { + LOG_INFO(Service_AM, "called"); + m_broker->GetOutData().Push(storage); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::PopInteractiveInData(Out<SharedPointer<IStorage>> out_storage) { + LOG_INFO(Service_AM, "called"); + R_RETURN(m_broker->GetInteractiveInData().Pop(out_storage)); +} + +Result ILibraryAppletSelfAccessor::PushInteractiveOutData(SharedPointer<IStorage> storage) { + LOG_INFO(Service_AM, "called"); + m_broker->GetInteractiveOutData().Push(storage); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetPopInDataEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_INFO(Service_AM, "called"); + *out_event = m_broker->GetInData().GetEvent(); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_INFO(Service_AM, "called"); + *out_event = m_broker->GetInteractiveInData().GetEvent(); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetLibraryAppletInfo( + Out<LibraryAppletInfo> out_library_applet_info) { + LOG_INFO(Service_AM, "called"); + *out_library_applet_info = { + .applet_id = m_applet->applet_id, + .library_applet_mode = m_applet->library_applet_mode, + }; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo( + Out<AppletIdentityInfo> out_identity_info) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_identity_info = { + .applet_id = AppletId::QLaunch, + .application_id = 0x0100000000001000ull, + }; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::CanUseApplicationCore(Out<bool> out_can_use_application_core) { + // TODO: This appears to read the NPDM from state and check the core mask of the applet. + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_can_use_application_core = false; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetMainAppletApplicationControlProperty( + OutLargeData<std::array<u8, 0x4000>, BufferAttr_HipcMapAlias> out_nacp) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + // TODO: this should be the main applet, not the caller applet + const auto application = GetCallerIdentity(*m_applet); + std::vector<u8> nacp; + const auto result = + system.GetARPManager().GetControlProperty(&nacp, application.application_id); + + if (R_SUCCEEDED(result)) { + std::memcpy(out_nacp->data(), nacp.data(), std::min(nacp.size(), out_nacp->size())); + } + + R_RETURN(result); +} + +Result ILibraryAppletSelfAccessor::GetMainAppletStorageId(Out<FileSys::StorageId> out_storage_id) { + LOG_INFO(Service_AM, "(STUBBED) called"); + *out_storage_id = FileSys::StorageId::NandUser; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::ExitProcessAndReturn() { + LOG_INFO(Service_AM, "called"); + system.GetAppletManager().TerminateAndRemoveApplet(m_applet->aruid); + m_broker->SignalCompletion(); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo( + Out<AppletIdentityInfo> out_identity_info) { + LOG_INFO(Service_AM, "called"); + *out_identity_info = GetCallerIdentity(*m_applet); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfoStack( + Out<s32> out_count, OutArray<AppletIdentityInfo, BufferAttr_HipcMapAlias> out_identity_info) { + LOG_INFO(Service_AM, "called"); + + std::shared_ptr<Applet> applet = m_applet; + *out_count = 0; + + do { + if (*out_count >= static_cast<s32>(out_identity_info.size())) { + break; + } + out_identity_info[(*out_count)++] = GetCallerIdentity(*applet); + } while ((applet = applet->caller_applet.lock())); + + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(Out<u32> out_desirable_layout) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_desirable_layout = 0; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::ReportVisibleError(ErrorCode error_code) { + LOG_WARNING(Service_AM, "(STUBBED) called, error {}-{}", error_code.category, + error_code.number); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::ReportVisibleErrorWithErrorContext( + ErrorCode error_code, InLargeData<ErrorContext, BufferAttr_HipcMapAlias> error_context) { + LOG_WARNING(Service_AM, "(STUBBED) called, error {}-{}", error_code.category, + error_code.number); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage( + Out<u64> out_desired_language) { + // FIXME: this is copied from IApplicationFunctions::GetDesiredLanguage + // FIXME: all of this stuff belongs to ns + auto identity = GetCallerIdentity(*m_applet); + + // TODO(bunnei): This should be configurable + LOG_DEBUG(Service_AM, "called"); + + // Get supported languages from NACP, if possible + // Default to 0 (all languages supported) + u32 supported_languages = 0; + + const auto res = [this, identity] { + const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(), + system.GetContentProvider()}; + auto metadata = pm.GetControlMetadata(); + if (metadata.first != nullptr) { + return metadata; + } + + const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_id), + system.GetFileSystemController(), + system.GetContentProvider()}; + return pm_update.GetControlMetadata(); + }(); + + if (res.first != nullptr) { + supported_languages = res.first->GetSupportedLanguages(); + } + + // Call IApplicationManagerInterface implementation. + auto& service_manager = system.ServiceManager(); + auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2"); + auto app_man = ns_am2->GetApplicationManagerInterface(); + + // Get desired application language + u8 desired_language{}; + R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages)); + + // Convert to settings language code. + u64 language_code{}; + R_TRY(app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language)); + + LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); + + *out_desired_language = language_code; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetCurrentApplicationId(Out<u64> out_application_id) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + // TODO: this should be the main applet, not the caller applet + const auto main_applet = GetCallerIdentity(*m_applet); + *out_application_id = main_applet.application_id; + + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers( + Out<bool> out_no_users_available, Out<s32> out_users_count, + OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users) { + const Service::Account::ProfileManager manager{}; + + *out_no_users_available = true; + *out_users_count = -1; + + LOG_INFO(Service_AM, "called"); + + if (manager.GetUserCount() > 0) { + *out_no_users_available = false; + *out_users_count = static_cast<s32>(manager.GetUserCount()); + + const auto users = manager.GetAllUsers(); + for (size_t i = 0; i < users.size() && i < out_users.size(); i++) { + out_users[i] = users[i]; + } + } + + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually( + Out<bool> out_should_set_gpu_time_slice_manually) { + LOG_INFO(Service_AM, "(STUBBED) called"); + *out_should_set_gpu_time_slice_manually = false; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::Cmd160(Out<u64> out_unknown0) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_unknown0 = 0; + R_SUCCEED(); +} + +} // namespace Service::AM |